package uk.co.revisual.domino.proxies {
	
	import org.puremvc.as3.multicore.patterns.proxy.Proxy;
	
	import uk.co.revisual.creation.DynamicClassFactory;
	import uk.co.revisual.domino.consts.DominoConsts;

	public class FSMClassFactoryProxy extends Proxy implements DynamicClassFactory
	{
	
		public function FSMClassFactoryProxy( factory:Class ):void{
			super( DominoConsts.PROXY_NAMES.FSM_CLASS_FACTORY_PROXY, new factory() );
		}
		
		public function addClass( item:Object ):Boolean{
			var incomingClasses:Array;
			if( item is Class )	incomingClasses = [ item ];
			else if( item is Array )incomingClasses = item as Array;			
			else return false;
			var newClassesToAdd:Array = filterIncomingClasses( incomingClasses );
			return ( factory.addClass( newClassesToAdd ) && incomingClasses.length == newClassesToAdd.length );
		}
		
		public function hasClass( item:Object ):Boolean{
			return factory.hasClass( item );
		}
		
		public function create( data:Object=null, asClass:Boolean=true ):Object{
			return factory.create( data, asClass );
		}
		
		private function filterIncomingClasses( classes:Array ):Array{
			var a:Array = [];
			for each ( var c:Class in classes ){
				var t:ClassTest = new ClassTest( c );
				if( t.test() ) a.push( c );
			}
			return a;
		}
		
		private function get factory():DynamicClassFactory{
			return DynamicClassFactory( data );
		}

	}
}
import flash.utils.describeType;

internal class ClassTest{
	internal var payload:Class;
	public function ClassTest( c:Class ):void{
		payload = c;
	}
	internal function test():Boolean{
		var description:XML = describeType( payload );
		return (	testForICommand( payload, description ) ||
					testForState( payload, description ) 	||
					testForSubState( payload, description )	); 
	}
	
	private function testForICommand( c:Class, description:XML ):Boolean{
		var interfaces:XMLList = description..implementsInterface.(@type == "org.puremvc.as3.multicore.interfaces::ICommand");
		return (interfaces.length() > 0 );
	}
	private function testForSubState( c:Class, description:XML ):Boolean{
		var extendsType:XMLList = description..extendsClass.(@type == "org.puremvc.as3.multicore.utilities.statemachine::State");
		return (extendsType.length() > 0 );
	}
	private function testForState( c:Class, description:XML ):Boolean{
		return ( description.@name == "org.puremvc.as3.multicore.utilities.statemachine::State" );
	}
}

